home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 May: Tool Chest / Dev.CD May 97 TC.toast / Sample Code / Networking / DumpARPCache / DumpARPCache.c next >
Encoding:
C/C++ Source or Header  |  1997-03-24  |  5.0 KB  |  177 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        DumpARPCache.c
  3.  
  4.     Contains:    Dumps the system ARP cache to stdout.
  5.  
  6.     Written by:    Quinn "The Eskimo!"
  7.  
  8.     Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.     You may incorporate this sample code into your applications without
  13.     restriction, though the sample code has been provided "AS IS" and the
  14.     responsibility for its operation is 100% yours.  However, what you are
  15.     not permitted to do is to redistribute the source as "DSC Sample Code"
  16.     after having made changes. If you're going to re-distribute the source,
  17.     we require that you make it clear in the source that the code was
  18.     descended from Apple Sample Code, but that you've made changes.
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23.  
  24. #include <OpenTptClient.h>
  25.  
  26. // Pick up the symbolic name of the OT ARP module.
  27.  
  28. #include <modnames.h>
  29.  
  30. // #include <miioccom.h>
  31.  
  32. // The following equates are actually exported by <miioccom.h>, but
  33. //  they commented out for some reason )-:
  34.  
  35. #define MIOC_ND            'c'        /* ioctl's for Mentat's nd device */
  36.  
  37. // The following equates define the two "Name Dispatch" ioctls
  38. // for setting and getting OT internal parameters.
  39.  
  40. #define ND_GET            MIOC_CMD(MIOC_ND, 0)    /* Get a value */
  41. #define ND_SET            MIOC_CMD(MIOC_ND, 1)    /* Set a value */
  42.  
  43. // The name of the Name Dispatch variable you have to get in
  44. // order to get a dump of the ARP cache.
  45.  
  46. #define ARP_ND_CACHE_REPORT "arp_cache_report"
  47.  
  48. /////////////////////////////////////////////////////////////////////
  49.  
  50. // A global static buffer to store the ARP cache report.  Obviously
  51. // a real application would have to allocate such a buffer dynamically.
  52.  
  53. static char gDataBuffer[10000];
  54.  
  55. static OSStatus DumpARPCache(void)
  56.     // Dump the OT ARP cache to stdout.
  57. {
  58.     OSStatus err;
  59.     StreamRef arpStream;
  60.     struct strioctl nddIOCommand;
  61.     SInt32 i;
  62.     
  63.     // First open up a raw STREAMS connection to the ARP module.
  64.     
  65.     arpStream = OTStreamOpen(MI_ARP_NAME, 0, &err);
  66.     
  67.     if (err == noErr) {
  68.  
  69.         // Switch the stream in sync/blocking mode.  To make the
  70.         // code easier, we're going to do this synchronously.
  71.  
  72.         (void) OTStreamSetBlocking(arpStream);
  73.         (void) OTStreamSetSynchronous(arpStream);
  74.         
  75.         // Copy the name of the ND variable we're trying
  76.         // to get into our buffer.
  77.  
  78.         OTStrCopy(gDataBuffer, ARP_ND_CACHE_REPORT);
  79.     
  80.         // The ND_GET ioctl returns a value and sets ic_len.  A negative
  81.         //  value is an error and you can give up now (-:  The rule for
  82.         //  positive values is a bit weirder.  ic_len is always set
  83.         //  to the amount of data that is actually returned.  If the
  84.         //  data available exceeds the available buffer space (as
  85.         //  defined by the ic_len on input), the ioctl returns
  86.         //  a positive number that is the amount of buffer space
  87.         //  needed.  So we first call it with a minimal buffer
  88.         //  then give it the buffer space it requires.  Obviously
  89.         //  there's a concurrency race here, which we conveniently
  90.         //  ignore in this sample.
  91.  
  92.         // First get the size of data buffer we need to allocate.
  93.         
  94.         nddIOCommand.ic_cmd = ND_GET;
  95.         nddIOCommand.ic_timout = 0;
  96.         nddIOCommand.ic_len = strlen(ARP_ND_CACHE_REPORT) + 1;    // Length of ND name including...
  97.         nddIOCommand.ic_dp = gDataBuffer;                        // ...the zero terminator.
  98.         
  99.         err = OTStreamIoctl(arpStream, I_STR, &nddIOCommand);
  100.         printf("First  OTStreamIoctl reports err    = %d\n", err);
  101.         printf("First  OTStreamIoctl reports ic_len = %d\n", nddIOCommand.ic_len);
  102.  
  103.         if (err >= noErr) {
  104.  
  105.             if (err > noErr) {
  106.             
  107.                 // The first ioctl returned a positive number telling
  108.                 // us how big the data returned was.  We turn around
  109.                 // around make the ioctl again, this time passing
  110.                 // in an appropriately sized buffer.
  111.                 
  112.                 OTStrCopy(gDataBuffer, ARP_ND_CACHE_REPORT);
  113.  
  114.                 nddIOCommand.ic_cmd = ND_GET;
  115.                 nddIOCommand.ic_timout = 0;
  116.                 nddIOCommand.ic_len = err;
  117.                 nddIOCommand.ic_dp = gDataBuffer;
  118.  
  119.                 err = OTStreamIoctl(arpStream, I_STR, &nddIOCommand);
  120.                 printf("Second OTStreamIoctl reports err    = %d\n", err);
  121.                 printf("Second OTStreamIoctl reports ic_len = %d\n", nddIOCommand.ic_len);
  122.             }
  123.             
  124.             if (err == noErr) {
  125.             
  126.                 // Everything is cool, let's print out the data
  127.                 // returned to us from ARP.  The format is straight
  128.                 // text with zero characters as the line terminator.
  129.                 
  130.                 err = noErr;
  131.                 for (i = 0; i < nddIOCommand.ic_len; i++) {
  132.                     if (gDataBuffer[i] == 0) {
  133.                         putchar('\n');
  134.                     } else {
  135.                         putchar(gDataBuffer[i]);
  136.                     }
  137.                 }
  138.             } else {
  139.                 printf("Whoah, ARP table changed size!\n");
  140.             }
  141.         }
  142.     }
  143.     
  144.     // Clean up.
  145.     
  146.     if (arpStream != nil) {
  147.         (void) OTStreamClose(arpStream);
  148.     }
  149.     return (err);
  150. }
  151.  
  152. /////////////////////////////////////////////////////////////////////
  153.  
  154. void main(void)
  155. {
  156.     OSStatus err;
  157.     
  158.     printf("Hello Cruel World!\n");
  159.     printf("DumpARPCache -- Dumps the Open Transport ARP cache to stdout\n\n");
  160.     
  161.     err = InitOpenTransport();
  162.     
  163.     if (err == noErr) {
  164.     
  165.         err = DumpARPCache();
  166.         
  167.         CloseOpenTransport();
  168.     }
  169.     
  170.     if (err == noErr) {
  171.         printf("Success.\n");
  172.     } else {
  173.         printf("Failed with error %d.\n", err);
  174.     }
  175.     printf("Done.  Press command-Q to Quit.\n");
  176. }
  177.